Skip to content

fix(evo-flow): reuse primary app context in action-node activities (EVO-1829)#75

Merged
dpaes merged 1 commit into
developfrom
fix/EVO-1829
Jun 18, 2026
Merged

fix(evo-flow): reuse primary app context in action-node activities (EVO-1829)#75
dpaes merged 1 commit into
developfrom
fix/EVO-1829

Conversation

@nickoliveira23

@nickoliveira23 nickoliveira23 commented Jun 18, 2026

Copy link
Copy Markdown

Summary

Journey/campaign action nodes (Add Label, Remove Label, Update Custom Attribute, Transfer Journey) + campaign-execution activities run outside the Nest DI container. Each one bootstrapped a full second AppModule via NestFactory.createApplicationContext(AppModule.forRoot()) just to resolve a DI service. In single-mode that boots a redundant Temporal worker + Kafka consumers + ScheduleModule jobs in the same process — they collide and the app silently freezes the first time an action node runs per boot (HTTP server dies, session stuck active on the node). Same family as EVO-1737, different path.

Fix (chosen via a design evaluation of 3 approaches): stash the primary application context at boot in a tiny module-level holder, and resolve services from it via getAppContext(). No second AppModule is ever booted. The primary context already provides every service these activities need and is guaranteed to exist before any activity dispatch.

Changes

  • src/shared/app-context.holder.ts (new): setAppContext/getAppContext (type-only import; fail-fast throw, never a silent hang).
  • src/main.ts: setAppContext(app) right after NestFactory.create() (before init/worker creation in all RUN_MODEs).
  • 4 action nodes + campaign-execution.activities.ts: resolve DI via getAppContext(); drop the per-node createApplicationContext(AppModule.forRoot()) bootstrap + dead imports.
  • no-app-bootstrap.guard.spec.ts (new): regression guard forbidding the bootstrap pattern under activities/.
  • Out of scope (documented): journey-tracking.activities.ts new KafkaService() (deliberate producer-only force-init).

Validation

  • evo-flow: npm run build → clean
  • evo-flow: npx jest (guard + campaign + add/remove-label + update-custom-attribute + conditional + split) → 64/64
  • evo-flow: npx prettier --check → new files + main + campaign spec clean (the 4 node files + campaign activity had pre-existing prettier drift on develop, intentionally not reformatted to keep the diff focused)
  • Live smoke (RUN_MODE=single, fix branch): a journey with an Add Label node — which froze the app before — now runs journey-trigger → add-label (started → completed) → exit, session completed, label applied, app stays up, and no second AppModule bootstrap appears in the logs.
  • Adversarial code review (multi-agent): 1 LOW (spec comment) fixed; the RLS/tenant and test-coverage concerns were verified as pre-existing / out-of-scope / inert in the single-tenant community build.

Acceptance Criteria

  • A journey with an action node runs in single-mode without freezing.
  • Action nodes still resolve their DI services and execute correctly (label applied live).
  • No second worker/consumer/scheduled-job started by an action node's DI bootstrap.
  • A/B repro: action-node journey completes without taking the process down.

Changed Files

  • src/shared/app-context.holder.ts (new)
  • src/main.ts
  • src/modules/temporal/activities/nodes/{add-label,remove-label,update-custom-attribute,transfer-journey}.node.ts
  • src/modules/temporal/activities/campaign-execution.activities.ts
  • src/modules/temporal/activities/campaign-execution.activities.spec.ts
  • src/modules/temporal/activities/no-app-bootstrap.guard.spec.ts (new)

Linked Issue

  • EVO-1829

🤖 Generated with Claude Code

Summary by Sourcery

Reuse the primary Nest application context for Temporal campaign and action-node activities instead of bootstrapping a second AppModule, preventing single-mode freezes and redundant workers.

Bug Fixes:

  • Ensure campaign-execution and action-node activities resolve dependencies from the primary Nest app context, avoiding secondary AppModule bootstraps that froze the app in single-mode.

Enhancements:

  • Introduce a shared app-context holder to stash and retrieve the primary Nest application context for out-of-container activities.
  • Update label, custom-attribute, and journey-transfer node activities to use the shared app context for dependency resolution instead of local NestFactory application contexts.

Tests:

  • Adjust campaign-execution activity tests to mock the new app-context holder and add a regression test guarding against reintroducing in-activity Nest bootstrap patterns.

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants